/*==============================================================================
案例 4：数据质量分析与清洗（数据准备与特征工程）
================================================================================

业务场景：
某公司收集了员工绩效数据，但数据质量参差不齐，存在缺失值、异常值、
重复记录等问题。需要进行全面的数据质量分析和清洗。

学习目标：
1. 掌握数据质量评估方法
2. 学习缺失值处理技术
3. 掌握异常值检测和处理
4. 学习数据标准化和转换

数据来源：nlsw88.dta（Stata 内置数据集）

作者：Stata ML Course
日期：2025-11-03
==============================================================================*/

clear all
set more off
capture log close

* 设置工作目录
cd "`c(pwd)'"

* 创建输出目录
capture mkdir "output/cases"
capture mkdir "output/cases/figures"
capture mkdir "data/cases"

* 开始日志记录
log using "output/cases/case04_data_quality.log", replace text

display "=========================================="
display "案例 4：数据质量分析与清洗"
display "=========================================="
display ""

/*------------------------------------------------------------------------------
第一部分：数据加载和初步检查
------------------------------------------------------------------------------*/

display "第一部分：数据加载和初步检查"
display "----------------------------"

* 加载数据
sysuse nlsw88, clear

* 基本信息
describe
display ""
display "数据集包含 " _N " 个观测，" c(k) " 个变量"

* 查看前几行数据
list in 1/5, clean

/*------------------------------------------------------------------------------
第二部分：数据质量评估
------------------------------------------------------------------------------*/

display ""
display "第二部分：数据质量评估"
display "----------------------"

* 1. 缺失值分析
display ""
display "1. 缺失值分析"
display "--------------"

* 生成缺失值统计表
misstable summarize, all

* 计算每个变量的缺失率
foreach var of varlist _all {
    quietly count if missing(`var')
    local miss_count = r(N)
    local miss_rate = (`miss_count' / _N) * 100
    display "`var': " %9.2f `miss_rate' "% 缺失"
}

* 可视化缺失值模式
graph hbar (count), over(grade) over(race) ///
    title("不同种族和教育水平的样本量") ///
    subtitle("检查数据分布均衡性") ///
    ytitle("样本数量") ///
    scheme(s2color)
graph export "output/cases/figures/case04_01_sample_distribution.png", replace

* 2. 数据类型检查
display ""
display "2. 数据类型检查"
display "--------------"

codebook wage hours ttl_exp tenure, compact

* 3. 数值范围检查
display ""
display "3. 数值范围检查"
display "--------------"

summarize wage hours ttl_exp tenure age grade, detail

* 4. 异常值检测（箱线图法）
display ""
display "4. 异常值检测"
display "--------------"

* 工资异常值检测
quietly summarize wage, detail
local q1 = r(p25)
local q3 = r(p75)
local iqr = `q3' - `q1'
local lower_bound = `q1' - 1.5 * `iqr'
local upper_bound = `q3' + 1.5 * `iqr'

count if wage < `lower_bound' | wage > `upper_bound'
display "工资异常值数量: " r(N)
display "下界: " %6.2f `lower_bound' ", 上界: " %6.2f `upper_bound'

* 可视化异常值
graph box wage, over(union) ///
    title("工资分布箱线图（按工会状态）") ///
    subtitle("识别异常值") ///
    ytitle("小时工资（美元）") ///
    scheme(s2color)
graph export "output/cases/figures/case04_02_wage_outliers.png", replace

/*------------------------------------------------------------------------------
第三部分：缺失值处理
------------------------------------------------------------------------------*/

display ""
display "第三部分：缺失值处理"
display "--------------------"

* 保存原始数据
preserve

* 策略 1：删除缺失值过多的观测（示例）
display ""
display "策略 1：删除缺失值"
display "------------------"

* 计算每行的缺失值数量
egen miss_count = rowmiss(_all)
display "缺失值分布："
tabulate miss_count

* 删除缺失值超过 3 个的观测
drop if miss_count > 3
display "删除后剩余观测数: " _N

restore
preserve

* 策略 2：均值插补
display ""
display "策略 2：均值插补"
display "----------------"

* 对工资进行均值插补（仅作示例）
quietly summarize wage
local mean_wage = r(mean)
replace wage = `mean_wage' if missing(wage)
display "工资缺失值已用均值插补: " %6.2f `mean_wage'

restore
preserve

* 策略 3：分组均值插补
display ""
display "策略 3：分组均值插补"
display "--------------------"

* 按行业和工会状态分组插补工资
bysort industry union: egen wage_group_mean = mean(wage)
replace wage = wage_group_mean if missing(wage)
display "工资缺失值已用分组均值插补"

restore

/*------------------------------------------------------------------------------
第四部分：异常值处理
------------------------------------------------------------------------------*/

display ""
display "第四部分：异常值处理"
display "--------------------"

* 策略 1：Winsorize（缩尾处理）
display ""
display "策略 1：Winsorize 处理"
display "----------------------"

* 对工资进行 1% 和 99% 分位数缩尾
quietly summarize wage, detail
local p1 = r(p1)
local p99 = r(p99)

gen wage_winsor = wage
replace wage_winsor = `p1' if wage < `p1'
replace wage_winsor = `p99' if wage > `p99'

display "原始工资范围: [" %6.2f r(min) ", " %6.2f r(max) "]"
quietly summarize wage_winsor
display "缩尾后范围: [" %6.2f r(min) ", " %6.2f r(max) "]"

* 对比可视化
twoway (histogram wage, color(blue%30)) ///
       (histogram wage_winsor, color(red%30)), ///
    title("工资分布对比：原始 vs Winsorize") ///
    subtitle("蓝色=原始，红色=缩尾处理") ///
    xtitle("小时工资（美元）") ///
    ytitle("密度") ///
    legend(order(1 "原始" 2 "Winsorize")) ///
    scheme(s2color)
graph export "output/cases/figures/case04_03_winsorize_comparison.png", replace

* 策略 2：对数转换
display ""
display "策略 2：对数转换"
display "----------------"

gen log_wage = log(wage)

* 对比转换前后的分布
twoway (histogram wage, width(1) color(blue%30)) ///
       (kdensity wage, lcolor(blue) lwidth(thick)), ///
    title("原始工资分布") ///
    xtitle("小时工资（美元）") ///
    ytitle("密度") ///
    legend(off) ///
    scheme(s2color) ///
    name(g1, replace)

twoway (histogram log_wage, width(0.1) color(red%30)) ///
       (kdensity log_wage, lcolor(red) lwidth(thick)), ///
    title("对数转换后工资分布") ///
    xtitle("log(小时工资)") ///
    ytitle("密度") ///
    legend(off) ///
    scheme(s2color) ///
    name(g2, replace)

graph combine g1 g2, ///
    title("对数转换效果对比") ///
    scheme(s2color)
graph export "output/cases/figures/case04_04_log_transformation.png", replace

/*------------------------------------------------------------------------------
第五部分：数据标准化
------------------------------------------------------------------------------*/

display ""
display "第五部分：数据标准化"
display "--------------------"

* Z-score 标准化
foreach var in wage hours ttl_exp tenure age {
    quietly summarize `var'
    gen `var'_std = (`var' - r(mean)) / r(sd)
    display "`var' 已标准化（均值=0，标准差=1）"
}

* 验证标准化结果
summarize wage_std hours_std ttl_exp_std tenure_std age_std

* Min-Max 归一化（0-1）
foreach var in wage hours ttl_exp tenure age {
    quietly summarize `var'
    gen `var'_norm = (`var' - r(min)) / (r(max) - r(min))
    display "`var' 已归一化到 [0, 1]"
}

* 验证归一化结果
summarize wage_norm hours_norm ttl_exp_norm tenure_norm age_norm

* 可视化标准化效果
graph box wage_std hours_std ttl_exp_std tenure_std age_std, ///
    title("标准化后的变量分布") ///
    subtitle("均值=0，标准差=1") ///
    ytitle("标准化值") ///
    scheme(s2color)
graph export "output/cases/figures/case04_05_standardization.png", replace

/*------------------------------------------------------------------------------
第六部分：数据质量报告
------------------------------------------------------------------------------*/

display ""
display "第六部分：数据质量报告"
display "----------------------"

* 生成数据质量摘要
display ""
display "数据质量摘要报告"
display "================"
display ""
display "1. 样本量: " _N
display "2. 变量数: " c(k)
display ""

* 缺失值统计
display "3. 缺失值情况："
misstable summarize wage hours ttl_exp tenure, all

* 异常值统计
display ""
display "4. 异常值情况（工资）："
count if wage < `lower_bound' | wage > `upper_bound'
display "   异常值数量: " r(N)
display "   异常值比例: " %5.2f (r(N)/_N*100) "%"

* 数据完整性评分
quietly count if !missing(wage) & !missing(hours) & !missing(ttl_exp) & !missing(tenure)
local complete_count = r(N)
local completeness = (`complete_count' / _N) * 100

display ""
display "5. 数据完整性评分: " %5.2f `completeness' "%"

/*------------------------------------------------------------------------------
第七部分：保存清洗后的数据
------------------------------------------------------------------------------*/

display ""
display "第七部分：保存清洗后的数据"
display "--------------------------"

* 保存清洗后的数据
save "data/cases/employee_data_cleaned.dta", replace
display "清洗后的数据已保存到: data/cases/employee_data_cleaned.dta"

* 导出 CSV 格式
export delimited using "output/cases/case04_cleaned_data.csv", replace
display "数据已导出为 CSV: output/cases/case04_cleaned_data.csv"

/*------------------------------------------------------------------------------
总结
------------------------------------------------------------------------------*/

display ""
display "=========================================="
display "案例 4 完成！"
display "=========================================="
display ""
display "主要成果："
display "1. 完成数据质量评估（缺失值、异常值、数据类型）"
display "2. 实施多种缺失值处理策略"
display "3. 实施异常值处理（Winsorize、对数转换）"
display "4. 完成数据标准化和归一化"
display "5. 生成 5 个数据质量可视化图表"
display "6. 保存清洗后的数据"
display ""
display "输出文件："
display "- 图表: output/cases/figures/case04_*.png (5个)"
display "- 数据: data/cases/employee_data_cleaned.dta"
display "- CSV: output/cases/case04_cleaned_data.csv"
display "- 日志: output/cases/case04_data_quality.log"
display ""

log close

